from fastapi import FastAPI
from tortoise import Tortoise, run_async
import uvicorn

from models import UserModel, UserInfoModel, PostModel, CommunityModel

app = FastAPI()


@app.get("/")
async def root():
    return {"message": "Hello World"}


async def create_data():
    for i in range(10):
        user = await UserModel.create(
            username=f"test{i+1}", password="123456", nickname=f"test{i+1}", email=f"test{i+1}@test.com"
        )
        await UserInfoModel.create(
            user=user,
            age=18 + i,
            sex="female" if i % 2 == 0 else "male",
            address=f"test no {i+1} address",
            phone=f"1234567890{i+1}",
            birth_date="1999-01-05",
        )
        await PostModel.create(
            user=user,
            title=f"test{i+1}-title",
            content=f"test{i+1}-content",
        )
        community = await CommunityModel.create(
            # members=[user.id],
            name=f"test{i+1}-community",
        )
        await community.members.add(user)


async def get_all_users():
    # 1. all()
    # users = await UserModel.all()
    # 2. fitter
    # users = await UserModel.filter(username__icontains="test")
    # 3. get() one user / get_or_none()
    # .prefetch_related("info") 可以预先加载关联的UserInfoModel
    user = await UserModel.get(username="test2").prefetch_related("info")
    print(user.info.age)
    # for user in users:
    #     print(user)


async def one_to_many_query():
    # user = await UserModel.get(username="test2").prefetch_related("posts")
    # if user and hasattr(user, "posts"):
    #     for post in user.posts:
    #         print(post.title, post.content, user.username)
    user = await UserModel.get(username="test2")
    posts = await user.posts.all().values("title", "content")
    result = {"username": user.username, "posts": []}
    for post in posts:
        result["posts"].append({"title": post["title"], "content": post["content"]})
    print(result)


async def many_to_one_query():
    post = await PostModel.get(title="test2 title").select_related("user")
    if post and hasattr(post, "user"):
        print(post.title, post.content, post.user.username)


async def many_to_many_query():
    # 0.1 增加关联数据
    # user = await UserModel.get(username="test2")
    # community = await CommunityModel.get(name="test3 community")
    # # await user.communities.add(community)
    # await community.members.add(user)
    # 0.2 移除关联数据
    # await user.communities.remove(community)
    # 1. 直接查询
    # user = await UserModel.get(username="test2")
    # communities = await user.communities.all()
    # for community in communities:
    #     print(community.name, user.username)
    # 2. 预先加载关联的CommunityModel
    user = await UserModel.get(username="test2").prefetch_related("communities")
    for community in user.communities:
        print(community.name, user.username)


async def update_user():
    user = await UserModel.get(username="test2")
    # 1. 传统对象更新.save()
    # user.nickname = "test1_new"
    # await user.save()  # 没有await的话，不会真正执行数据库操作，只是更新内存中的数据
    # 2. 字典更新.update_from_dict() 也要await user.save()保持入数据库
    # await user.update_from_dict({"nickname": "test2_new"})
    # await user.save()
    # 3. filter查询集批量修改
    await UserModel.filter(username__icontains="test").update(email="admin@test.com", password="654321")


async def delete_user():
    # 1. 查询集批量删除
    # await UserModel.filter(username="test10").delete()
    # 2. 对象单个删除
    user = await UserModel.get(username="test9")
    await user.delete()


async def init_db():
    await Tortoise.init(db_url="sqlite://db.sqlite3", modules={"models": ["models"]})

    # await Tortoise.generate_schemas()
    # await create_data()
    # await get_all_users()
    # await update_user()
    # await delete_user()
    await one_to_many_query()
    # await many_to_one_query()
    # await many_to_many_query()


# run_async(init_db())


if __name__ == "__main__":
    # uvicorn.run("main:app", host="127.0.0.1", port=8000, reload=True)
    run_async(init_db())
